﻿using System;
using System.Collections.Generic;

#if FRB_XNA

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;
#elif FRB_MDX

using Vector3 = Microsoft.DirectX.Vector3;
using Keys = Microsoft.DirectX.DirectInput.Key;

#endif

using FlatRedBall;
using FlatRedBall.Content.AnimationChain;

using FlatRedBall.Graphics.Animation;
using FlatRedBall.Input;
using FlatRedBall.Math.Geometry;
using FlatRedBall.Content;
using FlatRedBall.Instructions;
using System.Threading;
using System.Reflection;
using FlatRedBall.Gui;
using FlatRedBall.Graphics;
using FlatRedBall.Content.Particle;
using FlatRedBall.Graphics.Particle;

using FlatRedBall.ManagedSpriteGroups;
using FlatRedBall.Math;
using FlatRedBall.Content.Polygon;
using FlatRedBall.Graphics.Model;
using FlatRedBall.IO;
using FlatRedBallMdxTemplate1;

namespace YOUR_NAMESPACE.Screens
{
    class FrbSplashScreen : Screen
    {
        #region Fields
        //will contain the values of the current Camera position, velocity, 
        //orientation, etc to change it back when the SplashScreen is done
        private Vector3 mOldCameraPosition;
        private Vector3 mOldCameraVelocity;
        private Vector3 mOldCameraRotation;
        private Vector3 mOldCameraAcceleration;
        private Vector3 mOldCameraRotVel;

        private Vector3 mOldCameraRelativePos;
        private Vector3 mOldCameraRelativeAccel;
        private Vector3 mOldCameraRelativeVel;
        private Vector3 mOldCameraRelativeRot;
        private Vector3 mOldCameraRelativeRotVel;

        private float mFieldOfView;
        private bool mOrthogonal;

        //the Sprite containint the SplashScreen
        private Sprite mSplash;

        //Users must set this first, or an error will be signaled
        public static String NextScreen;
        #endregion

        #region Properties
        #endregion

        #region Event Methods
        #endregion

        #region Methods

        #region Constructor/Initialize

        public FrbSplashScreen()
            :
            base("FrbSplashScreen")
        {

        }

        public override void Initialize()
        {
            #region Store the original Camera info
            mFieldOfView = SpriteManager.Camera.FieldOfView;
            mOrthogonal = SpriteManager.Camera.Orthogonal;

            #region Camera Position
            //first, grab the Camera's current position and store it for later
            mOldCameraPosition.X = SpriteManager.Camera.X;
            mOldCameraPosition.Y = SpriteManager.Camera.Y;
            mOldCameraPosition.Z = SpriteManager.Camera.Z;
            #endregion

            #region Camera Velocity
            //grab the Camera's current Velocity and store it for later
            mOldCameraVelocity.X = SpriteManager.Camera.XVelocity;
            mOldCameraVelocity.Y = SpriteManager.Camera.YVelocity;
            mOldCameraVelocity.Z = SpriteManager.Camera.ZVelocity;
            #endregion

            #region Camera Rotation
            //grab the Camera's current Rotation and store it for later
            mOldCameraRotation.X = SpriteManager.Camera.RotationX;
            mOldCameraRotation.Y = SpriteManager.Camera.RotationY;
            mOldCameraRotation.Z = SpriteManager.Camera.RotationZ;
            #endregion

            #region Camera Acceleration
            //grab the Camera's current Acceleration and store it for later
            mOldCameraAcceleration.X = SpriteManager.Camera.XAcceleration;
            mOldCameraAcceleration.Y = SpriteManager.Camera.YAcceleration;
            mOldCameraAcceleration.Z = SpriteManager.Camera.ZAcceleration;
            #endregion

            #region Camera Rotation Velocity
            //grab the Camera's current Rotation Velocity and store it for later
            mOldCameraRotVel.X = SpriteManager.Camera.RotationXVelocity;
            mOldCameraRotVel.Y = SpriteManager.Camera.RotationYVelocity;
            mOldCameraRotVel.Z = SpriteManager.Camera.RotationZVelocity;
            #endregion

            #region Camera Relative Position
            //grab the Camera's current Relative Position and store it for later
            mOldCameraRelativePos.X = SpriteManager.Camera.RelativeX;
            mOldCameraRelativePos.Y = SpriteManager.Camera.RelativeY;
            mOldCameraRelativePos.Z = SpriteManager.Camera.RelativeZ;
            #endregion

            #region Camera Relative Acceleration
            //grab the Camera's current Relative Acceleration and store it for later
            mOldCameraRelativeAccel.X = SpriteManager.Camera.RelativeXAcceleration;
            mOldCameraRelativeAccel.Y = SpriteManager.Camera.RelativeYAcceleration;
            mOldCameraRelativeAccel.Z = SpriteManager.Camera.RelativeZAcceleration;
            #endregion

            #region Camera Relative Velocity
            //grab the Camera's current Relative Velocity and store it for later
            mOldCameraRelativeVel.X = SpriteManager.Camera.RelativeXVelocity;
            mOldCameraRelativeVel.Y = SpriteManager.Camera.RelativeYVelocity;
            mOldCameraRelativeVel.Z = SpriteManager.Camera.RelativeZVelocity;
            #endregion

            #region Camera Relative Rotation
            //grab the Camera's current Relative Rotation and store it for later
            mOldCameraRelativeRot.X = SpriteManager.Camera.RelativeRotationX;
            mOldCameraRelativeRot.Y = SpriteManager.Camera.RelativeRotationY;
            mOldCameraRelativeRot.Z = SpriteManager.Camera.RelativeRotationZ;
            #endregion

            #region Camera Relative Rotation Velocity
            //grab the Camera's current Relative Rotation Velocity and store it for later
            mOldCameraRelativeRotVel.X = SpriteManager.Camera.RelativeRotationXVelocity;
            mOldCameraRelativeRotVel.Y = SpriteManager.Camera.RelativeRotationYVelocity;
            mOldCameraRelativeRotVel.Z = SpriteManager.Camera.RelativeRotationZVelocity;
            #endregion
            #endregion

            #region Set Camera To Standard
            //then, set the Camera to a standard setting for the splashScreen
            SpriteManager.Camera.X = 0;
            SpriteManager.Camera.Y = 0;
            SpriteManager.Camera.Z = 40;

            SpriteManager.Camera.XVelocity = 0;
            SpriteManager.Camera.YVelocity = 0;
            SpriteManager.Camera.ZVelocity = 0;

            SpriteManager.Camera.RotationX = 0;
            SpriteManager.Camera.RotationY = 0;
            SpriteManager.Camera.RotationZ = 0;

            SpriteManager.Camera.XAcceleration = 0;
            SpriteManager.Camera.YAcceleration = 0;
            SpriteManager.Camera.ZAcceleration = 0;

            SpriteManager.Camera.RotationXVelocity = 0;
            SpriteManager.Camera.RotationYVelocity = 0;
            SpriteManager.Camera.RotationZVelocity = 0;

            SpriteManager.Camera.RelativeX = 0;
            SpriteManager.Camera.RelativeY = 0;
            SpriteManager.Camera.RelativeZ = 0;

            SpriteManager.Camera.RelativeXAcceleration = 0;
            SpriteManager.Camera.RelativeYAcceleration = 0;
            SpriteManager.Camera.RelativeZAcceleration = 0;

            SpriteManager.Camera.RelativeXVelocity = 0;
            SpriteManager.Camera.RelativeYVelocity = 0;
            SpriteManager.Camera.RelativeZVelocity = 0;

            SpriteManager.Camera.RelativeRotationX = 0;
            SpriteManager.Camera.RelativeRotationY = 0;
            SpriteManager.Camera.RelativeRotationZ = 0;

            SpriteManager.Camera.RelativeRotationXVelocity = 0;
            SpriteManager.Camera.RelativeRotationYVelocity = 0;
            SpriteManager.Camera.RelativeRotationZVelocity = 0;

            SpriteManager.Camera.FieldOfView = 0.7853982F;
            SpriteManager.Camera.Orthogonal = false;
            #endregion

            LoadScene(@"Content\FrbSplashScreen.scnx", null);

            //create the sprite and init it for the SplashScreen
            //pull the Sprite from the scene file
            mSplash = mSprites[0]; //there's only 1, so we already know where it is
            mSplash.Alpha = 0.0F;

            base.Initialize();
        }

        #endregion

        #region Public Methods

        public override void Activity(bool firstTimeCalled)
        {
            base.Activity(firstTimeCalled);

            mSplash.Instructions.Add(new Instruction<Sprite, float>(
                mSplash, "AlphaRate", 0.5F,
                TimeManager.CurrentTime + 0));

            mSplash.Instructions.Add(new Instruction<Sprite, float>(
                mSplash, "AlphaRate", -0.5F,
                TimeManager.CurrentTime + 4.0F));

            mSplash.Instructions.Add(new MethodInstruction<FrbSplashScreen>(
                this, "ActivityIsOver", new object[0],
                TimeManager.CurrentTime + 6.0F));

            if (AnyMouseButtonsPushed() || AnyKeysPushed() || AnyGamepadPushed())
            {
                //user wants to progress faster, so jump ahead 3 seconds so
                //the instruction can finish
                //mSplash.Instructions.Clear();
                mSplash.Instructions.ShiftTime(-3.0);

                mSplash.Instructions.Add(new Instruction<Sprite, float>(
                    mSplash, "AlphaRate", -0.5F,
                    TimeManager.CurrentTime + 0));

                mSplash.Instructions.Add(new Instruction<Sprite, float>(
                    mSplash, "Alpha", 0,
                    TimeManager.CurrentTime + 1.0F));

                mSplash.Instructions.Add(new MethodInstruction<FrbSplashScreen>(
                    this, "ActivityIsOver", new object[0],
                    TimeManager.CurrentTime + 1.0F));
            }
        }

        public override void Destroy()
        {
            SpriteManager.RemoveSprite(mSplash);

            //Now that we're done, reset the Camera position to what it was
            ResetCameraToOriginal();
            
            base.Destroy();
        }

        #endregion

        #region Private Methods


        private void ResetCameraToOriginal()
        {
            SpriteManager.Camera.X = mOldCameraPosition.X;
            SpriteManager.Camera.Y = mOldCameraPosition.Y;
            SpriteManager.Camera.Z = mOldCameraPosition.Z;

            SpriteManager.Camera.XVelocity = mOldCameraVelocity.X;
            SpriteManager.Camera.YVelocity = mOldCameraVelocity.Y;
            SpriteManager.Camera.ZVelocity = mOldCameraVelocity.Z;

            SpriteManager.Camera.RotationX = mOldCameraRotation.X;
            SpriteManager.Camera.RotationY = mOldCameraRotation.Y;
            SpriteManager.Camera.RotationZ = mOldCameraRotation.Z;

            SpriteManager.Camera.XAcceleration = mOldCameraAcceleration.X;
            SpriteManager.Camera.YAcceleration = mOldCameraAcceleration.Y;
            SpriteManager.Camera.ZAcceleration = mOldCameraAcceleration.Z;

            SpriteManager.Camera.RotationXVelocity = mOldCameraRotVel.X;
            SpriteManager.Camera.RotationYVelocity = mOldCameraRotVel.Y;
            SpriteManager.Camera.RotationZVelocity = mOldCameraRotVel.Z;

            SpriteManager.Camera.RelativeX = mOldCameraRelativePos.X;
            SpriteManager.Camera.RelativeY = mOldCameraRelativePos.Y;
            SpriteManager.Camera.RelativeZ = mOldCameraRelativePos.Z;

            SpriteManager.Camera.RelativeXAcceleration = mOldCameraRelativeAccel.X;
            SpriteManager.Camera.RelativeYAcceleration = mOldCameraRelativeAccel.Y;
            SpriteManager.Camera.RelativeZAcceleration = mOldCameraRelativeAccel.Z;

            SpriteManager.Camera.RelativeXVelocity = mOldCameraRelativeVel.X;
            SpriteManager.Camera.RelativeYVelocity = mOldCameraRelativeVel.Y;
            SpriteManager.Camera.RelativeZVelocity = mOldCameraRelativeVel.Z;

            SpriteManager.Camera.RelativeRotationX = mOldCameraRelativeRot.X;
            SpriteManager.Camera.RelativeRotationY = mOldCameraRelativeRot.Y;
            SpriteManager.Camera.RelativeRotationZ = mOldCameraRelativeRot.Z;

            SpriteManager.Camera.RelativeRotationXVelocity = mOldCameraRelativeRotVel.X;
            SpriteManager.Camera.RelativeRotationYVelocity = mOldCameraRelativeRotVel.Y;
            SpriteManager.Camera.RelativeRotationZVelocity = mOldCameraRelativeRotVel.Z;

            SpriteManager.Camera.FieldOfView = mFieldOfView;
            SpriteManager.Camera.Orthogonal = mOrthogonal;
        }

        private bool AnyGamepadPushed()
        {
#if FRB_XNA
            for (int i = 0; i < InputManager.Xbox360GamePads.Length; ++i)
            {
                if (InputManager.Xbox360GamePads[i].ButtonPushed(Xbox360GamePad.Button.A) ||
                    InputManager.Xbox360GamePads[i].ButtonPushed(Xbox360GamePad.Button.B) ||
                    InputManager.Xbox360GamePads[i].ButtonPushed(Xbox360GamePad.Button.X) ||
                    InputManager.Xbox360GamePads[i].ButtonPushed(Xbox360GamePad.Button.Y) ||
                    InputManager.Xbox360GamePads[i].ButtonPushed(Xbox360GamePad.Button.Start))
                    return true;
            }
#elif FRB_MDX
            for (int i = 0; i < InputManager.Joysticks.Count; i++)
            {
                Joystick joystick = InputManager.Joysticks[i];

                const int numberOfButtons = 8; // Check the first 8 buttons

                for (int buttonNumber = 0; buttonNumber < numberOfButtons; i++)
                {
                    if (joystick.Push(buttonNumber))
                    {
                        return true;
                    }
                }
            }
#endif


            return false;
        }

        private bool AnyKeysPushed()
        {
            bool enterPressed = false;

#if FRB_XNA
            enterPressed = InputManager.Keyboard.KeyPushed(Keys.Enter);
#elif FRB_MDX
            enterPressed = InputManager.Keyboard.KeyPushed(Keys.Return);
#endif

            if (enterPressed ||
                InputManager.Keyboard.KeyPushed(Keys.Escape) ||
                InputManager.Keyboard.KeyPushed(Keys.Space))
                return true;
            else
                return false;

        }

        private bool AnyMouseButtonsPushed()
        {
            if (InputManager.Mouse.ButtonPushed(FlatRedBall.Input.Mouse.MouseButtons.LeftButton) ||
                InputManager.Mouse.ButtonPushed(FlatRedBall.Input.Mouse.MouseButtons.RightButton) ||
                InputManager.Mouse.ButtonPushed(FlatRedBall.Input.Mouse.MouseButtons.MiddleButton))
                return true;
            else
                return false;

        }

        private void ActivityIsOver()
        {
            //set base.NextScreen to the next Screen (stored in NextScreen)
            IsActivityFinished = true;
            base.NextScreen = NextScreen;
        }

        #endregion

        #endregion

    }
}
